#ifndef BTREESTORE_H
#define BTREESTORE_H

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct info {
    uint32_t size;
    uint32_t key[4];
    uint64_t nonce;
    void * data;
};

struct node {
    uint16_t num_keys;
    uint32_t* keys;
    //the children of current node
    struct node** child;
    //the parent of current node
    struct  node* parent;
    //data of node
    struct info* data;
};


struct b_tree {
    uint16_t min_val;
    uint16_t max_val;
    uint16_t mid_index;
    struct node* root;
};

void * init_store(uint16_t branching, uint8_t n_processors);

void close_store(void * helper);

int btree_insert(uint32_t key, void *plaintext, size_t count, uint32_t encryption_key[4], uint64_t nonce,  void * helper);

int btree_retrieve(uint32_t key, struct info * found, void * helper);



int btree_decrypt(uint32_t key, void * output, void * helper);

int btree_delete(uint32_t key, void * helper);

uint64_t btree_export(void * helper, struct node ** list);

void encrypt_tea(uint32_t plain[2], uint32_t cipher[2], uint32_t key[4]);

void decrypt_tea(uint32_t cipher[2], uint32_t plain[2], uint32_t key[4]);

void encrypt_tea_ctr(uint64_t * plain, uint32_t key[4], uint64_t nonce, uint64_t * cipher, uint32_t num_blocks);

void decrypt_tea_ctr(uint64_t * cipher, uint32_t key[4], uint64_t nonce, uint64_t * plain, uint32_t num_blocks);

void count_tree_node(struct node *root, uint64_t *pos);

int borrowKey(struct node * node, struct b_tree *b_tree);

struct node *create_tree_node(struct b_tree *b_tree);

void* create_info(void * plaintext, size_t count, uint32_t encryption_key[4], uint64_t nonce, void *helper);

int merge_node(struct node * left_brother_node, struct node * right_brother_node, uint32_t idx, struct b_tree* b_tree);

void close_node(struct node* node, struct node* root);

void visit_node(struct node *root, uint64_t *pos, struct node **list);

#endif
